/*
 * @Author: master
 * @Date: 2021-09-04 19:36:03
 * @LastEditTime: 2022-04-08 11:08:11
 * @Description: http请求
 */
'use strict';
import axios from 'axios';
import { dealError, statusCode } from './abnormal'; // 异常处理
import _ from 'lodash';
// 默认定义过期时长
const defaultTimeout = 60000;
axios.defaults.timeout = defaultTimeout;
// request 拦截器
axios.interceptors.request.use(
  config => config,
  error => {
    return Promise.reject(error);
  },
);
// response 拦截器(响应拦截器即异常处理)
axios.interceptors.response.use(
  response => response,
  error => {
    /**
     * 超时处理
     */
    if (error?.message?.includes('timeout')) {
      return Promise.reject(statusCode('timeout'));
    }
    if (error?.message?.includes('Network')) {
      return Promise.reject(statusCode('Network'));
    }
    if (error?.response) {
      // 错误处理
      return Promise.reject(dealError(error, error.response));
    }
    return Promise.reject(error?.response);
  },
);
/**
 * 数据操作类型（get、delete）
 * @param url
 * @param option
 */
const sendGetDelete = (url, options) => {
  const { method = 'get' } = options;
  const promise = new Promise((resolve, reject) => {
    // 判断是否为对象，同时是否存在自定义options
    if (_.isObject(options.custom)) {
      options = { ...options, ...options.custom };
    }
    axios[method](url, options).then(
      response => {
        resolve(response.data);
      },
      err => {
        if (err) {
          console.error('err', err);
          reject(err);
        }
      },
    );
  });
  if (options.isCancel) {
    return { promise: promise, cancel: options.cancel };
  }
  return promise;
};
/**
 * 数据操作类型（post、put、delete、patch）
 * @param url
 * @param options
 */
const optionMethod = (url, options) => {
  const { method = 'post' } = options;
  const body = setOptionMethodBody(options); // 转换body数据格式和类型
  const promise = new Promise((resolve, reject) => {
    // 当前options
    let curOptions = {
      cancelToken: options.cancelToken,
      headers: options.headers,
      timeout: options?.timeout || defaultTimeout,
    };
    // 判断是否为对象，同时是否存在自定义options
    if (_.isObject(options.custom)) {
      curOptions = { ...curOptions, ...options.custom };
    }
    axios[method](url, body, curOptions).then(
      response => {
        resolve(response.data);
      },
      err => {
        if (err) {
          console.error('err', err);
          reject(err);
        }
      },
    );
  });
  if (options.isCancel) {
    return { promise: promise, cancel: options.cancel };
  }
  return promise;
};
/**
 * 转换body数据格式和类型
 */
const setOptionMethodBody = options => {
  const { data } = options;
  if (!data) {
    return {};
  }
  if (options.type === 'form') {
    // 为了正常传递form表单,需要设置charset=UTF-8
    let formData = new URLSearchParams();
    if (options?.noUtf8) {
      formData = new FormData();
    }
    for (const key of Object.keys(data)) {
      if (Object.prototype.toString.call(data[key]) === '[object Array]') {
        data[key].map(item => {
          formData.append(key, item);
        });
      } else {
        formData.append(key, data[key]);
      }
    }
    return formData;
  } else if (options.type === 'json') {
    return JSON.stringify(data);
  } else {
    return data;
  }
};
/**
 * 取消请求源
 */
const cancelSource = () => {
  const { token, cancel } = axios.CancelToken.source();
  return { token, cancel };
};
/**
 * 请求
 * @param {string} 请求路径
 * @param {options} 参数
 * options.data 请求参数
 * options.method 请求方式：get/post/patch/put/delete
 * options.type 传参类型 form/json
 * options.isCancel 是否取消请求 true/false 当isCancel为true的时候，会返回一个object,可以直接object.cancel()来取消请求
 */
const http = (url, options = { method: 'get' }) => {
  const { token, cancel } = cancelSource();
  Object.assign(options, {
    cancelToken: token,
    cancel: cancel,
    method: options?.method?.toLowerCase(),
  });
  if (!options?.method) {
    options.method = 'get';
  }
  if (options.method === 'get' || options.method === 'delete') {
    // get和delete方式
    return sendGetDelete(url, Object.assign({}, { params: options.data || {} }, options));
  } else {
    return optionMethod(url, options); // 数据操作类型（post、put、delete、patch）
  }
};
/**
 * 存在模拟登录
 */
if (viteConfig?.simulation?.commandResult && viteConfig.nodeEnv === 'dev') {
  if (viteConfig?.simulation?.customHeaderTokenKey && viteConfig?.simulation?.customDataJwtToken) {
    axios.defaults.headers[viteConfig.simulation.customHeaderTokenKey] =
      viteConfig.simulation.commandResult[viteConfig.simulation.customDataJwtToken];
    /**
     * 权限刷新
     */
    const reflashAuth = () => {
      http(`${viteConfig.simulation.http}/auth/reflash`, {
        data: { pcLogin: true },
      });
      setTimeout(() => {
        reflashAuth();
      }, 90 * 1000);
    };
    reflashAuth();
  } else if (viteConfig?.simulation?.commandToken) {
    axios.defaults.headers = {
      commandToken: viteConfig.simulation.commandToken,
    };
  }
}
export default http;
